package cn.com.sparkle.paxos.stablestorage;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

import com.google.protobuf.ByteString;

import cn.com.sparkle.paxos.checksum.ChecksumUtil;
import cn.com.sparkle.paxos.checksum.ChecksumUtil.UnsupportedChecksumAlgorithm;
import cn.com.sparkle.paxos.deamon.InstanceExecutor;
import cn.com.sparkle.paxos.model.Value.ValueType;
import cn.com.sparkle.paxos.net.client.system.callback.PrepareCallBack;
import cn.com.sparkle.paxos.stablestorage.ReadSuccessRecordCallback.SuccessfulRecordWrap;
import cn.com.sparkle.paxos.stablestorage.event.PrepareRecordRealWriteEvent;
import cn.com.sparkle.paxos.stablestorage.io.BufferedFileOut;
import cn.com.sparkle.paxos.stablestorage.model.RecordType;
import cn.com.sparkle.paxos.stablestorage.model.StoreModel.Id;
import cn.com.sparkle.paxos.stablestorage.model.StoreModel.InstanceVoteRecord;
import cn.com.sparkle.paxos.stablestorage.model.StoreModel.SuccessfulRecord;
import cn.com.sparkle.paxos.stablestorage.model.StoreModel.Value;

public class NewTestWritePerformance {

	public static void testBatchWrite(int testSize, int valueSize, RecordType type) throws ClassNotFoundException,
			IOException, UnsupportedChecksumAlgorithm {
		RecordFileOperator o = new RecordFileOperator(new File("c:/jdpaxos/test1/success"), 0, new InstanceExecutor(
				null, null) {
			@Override
			public void execute(SuccessfulRecordWrap record) {
			}
		}, ChecksumUtil.PURE_JAVA_CRC32, true);
		o.init();
		System.out.println(o.getLastExpectSafeInstanceId());
		System.out.println(o.getVotedInstanceRecordMap().size());
		ByteString bs = ByteString.copyFrom(new byte[valueSize]);

		Value v = Value.newBuilder().setType(ValueType.ADMIN.getValue()).addValues(bs).build();
		Id id = Id.newBuilder().setAddress("").setIncreaseId(0).build();
		long ct = System.currentTimeMillis();
		for (int i = 0; i < testSize; i++) {
			if (type == RecordType.SUCCESS) {
				SuccessfulRecord.Builder record = SuccessfulRecord.newBuilder().setV(v);
				o.writeSuccessfulRecord(i, record, null, null);
			} else {
				InstanceVoteRecord.Builder b = InstanceVoteRecord.newBuilder();
				b.setHighestJoinNum(id).setHighestValue(v).setHighestVotedNum(id);
				InstanceVoteRecord r = b.build();
				o.writeVoteRecord(i, r, null);
			}
		}
		System.out.println(testSize / ((double) (System.currentTimeMillis() - ct) / 1000) + " success/s");
	}

	public static void testWrite(int testSize, int valueSize, RecordType type) throws ClassNotFoundException,
			IOException, InterruptedException, UnsupportedChecksumAlgorithm {
		RecordFileOperator o = new RecordFileOperator(new File("c:/jdpaxos/test1/success"), 0, new InstanceExecutor(
				null, null) {
			@Override
			public void execute(SuccessfulRecordWrap record) {
			}
		}, ChecksumUtil.PURE_JAVA_CRC32, true);
		o.init();
		Id id = Id.newBuilder().setAddress("").setIncreaseId(0).build();
		ByteString bs = ByteString.copyFrom(new byte[valueSize]);
		Value v = Value.newBuilder().setType(ValueType.ADMIN.getValue()).addValues(bs).build();

		long ct = System.currentTimeMillis();
		for (int i = 0; i < testSize; i++) {
			final CountDownLatch count = new CountDownLatch(1);

			if (type == RecordType.SUCCESS) {
				Callable<Object> callable = new Callable<Object>() {

					@Override
					public Object call() throws Exception {
						// TODO Auto-generated method stub
						count.countDown();
						return null;
					}

				};
				SuccessfulRecord.Builder record = SuccessfulRecord.newBuilder().setV(v).setHighestVoteNum(id);
				o.writeSuccessfulRecord(i, record, null, callable);
			} else {
				PrepareRecordRealWriteEvent event = new PrepareRecordRealWriteEvent() {

					@Override
					public void successWrite(long instanceId, InstanceVoteRecord record) {
						count.countDown();

					}

					@Override
					public void instanceSucceeded(long instanceId, SuccessfulRecord record) {
						count.countDown();
						
					}

					@Override
					public void instanceExecuted(long instanceId) {
						count.countDown();
					}
				};
				InstanceVoteRecord.Builder b = InstanceVoteRecord.newBuilder();
				b.setHighestJoinNum(id).setHighestValue(v).setHighestVotedNum(id);
				InstanceVoteRecord r = b.build();
				o.writeVoteRecord(i, r, event);
			}
			count.await();
		}
		System.out.println(testSize / ((double) (System.currentTimeMillis() - ct) / 1000) + " success/s");
	}

	public static void main(String[] args) {
		BufferedFileOut.init(false);
		Thread t1 = new Thread() {
			public void run() {
				try {
					testWrite(1, 1024, RecordType.VOTE);
				} catch (Throwable e) {
					e.printStackTrace();
				}
			}
		};
		Thread t2 = new Thread() {
			public void run() {
				try {
					//					testBatchWrite(10000,1024,RecordType.SUCCESS);
					testWrite(1000, 1024 * 1024, RecordType.SUCCESS);
				} catch (Throwable e) {
					e.printStackTrace();
				}
				/*catch (InterruptedException e) {
					e.printStackTrace();
				}*/
			}
		};
//		t1.start();
		t2.start();

	}
}
